/*
 * Archivo.cpp
 *
 *  Created on: 18 Apr 2010
 *      Author: osky
 */
#include "Archivo.h"

Archivo* Archivo::_instance = NULL;

char* Archivo::name;

unsigned int Archivo::tamanioMaximoBloque = 0;

Archivo::Archivo(char* nombre,const char* modo) {

	this->arch = fopen(nombre, modo);
	if (this->arch) {

		char* bitmap = new char[cantidadBloques];

		inicializarCadenas(bitmap, cantidadBloques);

		fwrite((void*) bitmap, sizeof(char), cantidadBloques, this->arch);

		delete[] bitmap;
	}
}

void Archivo::inicializarCadenas(char* cadenaVacia, int size){

	for (int i = 0; i < size; i++) {

				cadenaVacia[i] = 0;
	}


}

int Archivo::getBloqueLibre() {

	char *bitmap = new char[cantidadBloques];
	fseek(this->arch, 0, SEEK_SET);
	fread((void*) bitmap, sizeof(char), cantidadBloques, this->arch);

	int i = 0;

	int j = 0;
	char mascara = 1;

	char valorAnd;

	while (j < cantidadBloques) {

		while ((i < 8)) {

			valorAnd = bitmap[j] & mascara;

			if (valorAnd == 0) {

				bitmap[j] = bitmap[j] ^ mascara;

				fseek(this->arch, 0, SEEK_SET);

				fwrite((void*) bitmap, sizeof(char), cantidadBloques, this->arch);

				int numeroBloque = (j * 8) + (i);

				char *Bloque = new char[tamanioMaximoBloque];

				inicializarCadenas(Bloque, tamanioMaximoBloque);

				fseek(this->arch, primerBloque + numeroBloque * tamanioMaximoBloque, SEEK_SET);

				fwrite((void*) Bloque, sizeof(char), tamanioMaximoBloque, this->arch);

				delete[] Bloque;

				delete[] bitmap;

				return numeroBloque;

			} else {

				mascara <<= 1;
				i++;

			}

		}
		j++;
		i = 0;
		mascara = 1;
	}
	return false;
}

void Archivo::borrarBloque(int numeroBloque) {

	int mascara = 1;

	int posicionBitmap = numeroBloque / 8;

	int posicionBit = numeroBloque - posicionBitmap * 8;

	mascara <<= posicionBit;

	mascara = ~mascara;

	char* bitmap = new char[cantidadBloques];

	fseek(this->arch, 0, SEEK_SET);

	fread((void*) bitmap, sizeof(char), cantidadBloques, this->arch);

	bitmap[posicionBitmap] = bitmap[posicionBitmap] & mascara;

	fseek(this->arch, 0, SEEK_SET);

	fwrite((void*) bitmap, sizeof(char), cantidadBloques, this->arch);

	delete [] bitmap;
}


Archivo* Archivo::getInstance(const char* modo) {

	if (modo) {

		if (_instance!=NULL){
			delete _instance;
		}
		_instance = new Archivo(name, modo);
		if (_instance->arch == NULL) {
			delete _instance;
			_instance = NULL;
			return NULL;
		}
		return _instance;

	} else {

		if (!_instance) {
			_instance = new Archivo(name, "w+");
		}

	}
	return _instance;
}

void Archivo::setTamanioBloque(int tamanioBloque) {

	tamanioMaximoBloque = tamanioBloque;

}

void Archivo::setNombre(const char* nombre) {

	name = const_cast<char*>(nombre);

}
void Archivo::write(stringstream *bloque, int numeroBloque) {

	int posicion = numeroBloque * tamanioMaximoBloque;

	fseek(this->arch, primerBloque + posicion, SEEK_SET);

	int tamanioEscritura = 0;

	if (bloque->str().length() < tamanioMaximoBloque) {

		tamanioEscritura = bloque->str().length();

	} else {
		tamanioEscritura = tamanioMaximoBloque;
	}

	fwrite((void*)(bloque->str().c_str()), sizeof(char),tamanioEscritura,this->arch);


}

stringstream* Archivo::read(int numeroBloque) {

	int posicion = numeroBloque * tamanioMaximoBloque;

	fseek(this->arch, primerBloque + posicion, SEEK_SET);

	char *bufferIntermedio = new char[tamanioMaximoBloque];

	stringstream *nodo = new stringstream(ios::in | ios::out | ios::trunc | ios::binary);

	fread((void*)(bufferIntermedio), sizeof(char),tamanioMaximoBloque,this->arch);

	nodo->write(bufferIntermedio, tamanioMaximoBloque);

	delete[] bufferIntermedio;

	return nodo;
}

Archivo::~Archivo() {

	if (this->arch){

		fclose(this->arch);

	}

}

void Archivo::deleteInstance() {

	delete _instance;
	_instance = NULL;
}

